import os
from functools import cache

import bpy


@cache
def _valid_path(path):
    """反回"""
    is_file = os.path.isfile(path)
    is_bl = is_file and QueueUtils.is_bl_file(path)
    return is_file and is_bl


@cache
def _byte_to_mb(size: float) -> float:
    """字节转mb"""
    return size / 1024 / 1024


@cache
def from_file_get_file_size(file_path: str) -> float:
    """从文件获取文件大小"""
    return os.stat(file_path).st_size


class QueueUtils:
    render_queue = []  # 渲染队列,每一个添加到渲染队列中的项都应在列表内,总表

    render_state_items = [
        ('NOT_RENDER', '待渲染', '未渲染并且未在队列中'),
        ('IN_QUEUE', '队列中', '已在渲染队列中,但还未渲染'),

        ('RENDERED', '已渲染', '已经渲染完成并输入图像的'),

        ('IN_RENDER', '渲染中', '渲染中的物体有且只能有一个'),
        ('PAUSE_RENDER', '暂停渲染', '已在队列中但停止了的'),
        ('RENDER_ERROR', '渲染错误', '渲染过程中出现了错误'),
        ('FILE_ERROR', '文件错误', '需要被渲染的文件出现了错误,如被删除或未被删除但渲染闪退')
    ]

    @cache
    def pref_(self=None):
        """缓存偏好设置
        @return: AddonProperty
        """
        return QueueUtils.static_pref_()

    @staticmethod
    def clear_cache():
        """清除缓存"""
        from_file_get_file_size.cache_clear()
        _valid_path.cache_clear()

    @property
    def enabled_render_master(self) -> bool:
        """启用了 渲染主插件的"""
        return 'render_master' in bpy.context.preferences.addons

    @staticmethod
    def is_bl_file(path: str):
        """反回输入路径是.blend的布尔值
        不分大小写"""
        suffix = os.path.splitext(path)[1]
        return suffix.lower() == '.blend'

    @staticmethod
    def static_pref_(string=False) -> 'RenderQueueAddonPreferences':
        """
        反回插件属性并缓存
        每一次开关插件都需要清除缓存
        静态方法
        """
        from .preferences import RenderQueueAddonPreferences
        bl_idname = RenderQueueAddonPreferences.bl_idname
        if string:
            return f'preferences.addons["{bl_idname}"].preferences'
        return bpy.context.preferences.addons[bl_idname].preferences

    @staticmethod
    def stop_render():
        pref = QueueUtils.pref_()
        if pref and pref.active_render:
            pref.active_render.stop_render()

    @property
    def pref(self) -> 'RenderQueueAddonPreferences':
        """反回插件属性"""
        pref = QueueUtils.pref_()
        if not pref:
            QueueUtils.pref_.cache_clear()
            return self.pref

        return pref

    @property
    def active_render(self):
        """反回活动渲染项"""

        items = getattr(self.pref, 'render_items', None)

        def index():
            ind = self.pref.active_index
            if len(items) - 1 >= ind >= 0:
                return ind
            return -1  # 超出索引值

        if items:
            return items[index()]

    # render info
    def _get_render_items(self, state: str):
        """获取渲染状态为输入的项
        """

        if self.pref and getattr(self.pref, 'render_items', None):
            return list(i for i in self.pref.render_items if i.render_state == state)
        self.pref_.cache_clear()
        return []

    @property
    def render_not_items(self):
        """待渲染"""
        return self._get_render_items('NOT_RENDER')

    @property
    def render_in_queue_items(self):
        """队列中项"""
        return self._get_render_items('IN_QUEUE')

    @property
    def render_in_item(self):
        """正在渲染项
        """
        in_render = self._get_render_items('IN_RENDER')
        if in_render:
            return in_render[0]

    @property
    def render_pause_items(self):
        """
        暂停渲染项
        """
        return self._get_render_items('PAUSE_RENDER')

    @property
    def render_finished_items(self):
        """渲染完成项"""
        return self._get_render_items('RENDERED')

    @property
    def render_error_items(self):
        """渲染错误项"""
        return self._get_render_items('RENDER_ERROR')

    @property
    def render_next_item(self):
        """反回下一下需要渲染的物体
        从渲染队列未被渲染的里面拿
        """
        items = self.render_in_queue_items
        if items:
            return items[0]

    @property
    def show_render_sum_progress(self) -> bool:
        """反回是否显示总进度的布尔值"""
        return self.render_in_item or self.render_queue

    @property
    def selected_queue(self):
        """        反回所选中的队列渲染项        """
        return list(i for i in self.pref.render_items if i.selected)
